﻿using CommandProcessor.Dispatcher;
using Data.Repositories;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using PagedList;
using AutoMapper;
using QuanLySanXuat.Models;
using Domain.Commands;
using Core.Common;
using Core.Extensions;
using Data.Models;


namespace QuanLySanXuat.Controllers
{
    public class OrderProcessController : Controller
    {
        private readonly ICommandBus commandBus;
        private readonly IOrderProcessRepository oderProcessRepository;
        private readonly IOrderRepository oderRepository;
        private readonly IUOMRepository uomRepository;
        private readonly ISubprocessDetailRepository subprocessRepository;
        private readonly IDesignDetailRepository designRepository;
        private readonly IEmployeeRepository employeeRepository;
        private readonly IUnitRepository unitRepository;
        private readonly IWorkplaceRepository workplaceRepository;
        private readonly IMaterialDetailRepository materialDetailRepository;
        private readonly IToolDetailRepository toolDetailRepository;
        private readonly IOtherCostDetailRepository otherDetailRepository;
        private readonly ILabourDetailRepository labourDetailRepository;
        private readonly ILabourFormulaRepository labourFormualRepository;
        private readonly IMaterialFormulaRepository materialFormulaRepository;
        private readonly IOtherCostFormulaRepository othercostFormulaRepository;
        private readonly IToolFormulaRepository toolFormulaRepository;
        private readonly ICostDetailRepository costDetailRepository;

        public OrderProcessController(ICommandBus commandBus, IOrderProcessRepository oderProcessRepository, IOrderRepository oderRepository, IUOMRepository uomRepository, ISubprocessDetailRepository subprocessRepository, IDesignDetailRepository designRepository, IEmployeeRepository employeeRepository, IUnitRepository unitRepository, IWorkplaceRepository workplaceRepository, IMaterialDetailRepository materialDetailRepository, IToolDetailRepository toolDetailRepository, IOtherCostDetailRepository otherDetailRepository, ILabourDetailRepository labourDetailRepository, ILabourFormulaRepository labourFormualRepository, IMaterialFormulaRepository materialFormulaRepository, IOtherCostFormulaRepository othercostFormulaRepository, IToolFormulaRepository toolFormulaRepository, ICostDetailRepository costDetailRepository)
        {
            this.commandBus = commandBus;
            this.oderProcessRepository=oderProcessRepository;
            this.oderRepository = oderRepository;
            this.uomRepository = uomRepository;
            this.subprocessRepository = subprocessRepository;
            this.designRepository = designRepository;
            this.unitRepository = unitRepository;
            this.workplaceRepository = workplaceRepository;
            this.employeeRepository = employeeRepository;
            this.labourDetailRepository = labourDetailRepository;
            this.materialDetailRepository = materialDetailRepository;
            this.otherDetailRepository = otherDetailRepository;
            this.toolDetailRepository = toolDetailRepository;
            this.toolFormulaRepository = toolFormulaRepository;
            this.materialFormulaRepository = materialFormulaRepository;
            this.labourFormualRepository = labourFormualRepository;
            this.othercostFormulaRepository = othercostFormulaRepository;
            this.costDetailRepository = costDetailRepository;
        }
        //
        // GET: /OderProcess/

        public ActionResult Index()
        {
            //Lay ra cac danh sach lenh thuc hien lenh san xuat
            var oderProcess = oderProcessRepository.GetAll();
            return View(oderProcess.ToPagedList(1, 10));
        }
        public ActionResult Create(int? ID)
        {
            if (ID == null)
            {
                ViewData["Order"] = oderRepository.GetAll();
            }
            else {
                ViewData["Order"] = oderRepository.GetAll();
                //ViewData["Order"] = oderRepository.GetMany(x => x.Status == 1);
            }
            
            ViewData["DesignDetail"]=designRepository.GetAll();
            ViewData["DesignDetail"] = designRepository.GetAll();
            ViewData["Unit"] = unitRepository.GetAll();
            ViewData["Employee"] = employeeRepository.GetAll();
            ViewData["Workplace"] = workplaceRepository.GetAll();
            var oderProcess = oderProcessRepository.GetById(ID ?? 0);
            var oderprocessForm = Mapper.Map<OrderProcess, OrderProcessFormModels>(oderProcess);
            if (oderprocessForm != null)
            {
                oderprocessForm.SubprocessDetailsFormModels = subprocessRepository.GetMany(x => x.OrderProcessID == ID).ToList();
                oderprocessForm.CostDetailsFormModels = costDetailRepository.GetMany(x => x.OrderProcessID == ID).ToList();
            }
            return View(oderprocessForm);
        }

        public ActionResult GetDetail(int ID)
        {
            var order = oderRepository.GetById(ID);
            var design = designRepository.GetMany(x => x.ProductModelID == order.ProductModelID);
            List<CostDetail> costDetailsFormModels = new List<CostDetail>();
            List<SubprocessDetail> subProcess = new List<SubprocessDetail>();
            foreach (var item in design)
            {
                //
                var subPro = new SubprocessDetail()
                  {
                      DesignDetail=item
                  };
                subProcess.Add(subPro);


                //Bang costdetail
                var materials = materialFormulaRepository.GetMany(x => x.DesignDetailID == item.ID);
                double materialCost = 0;
                foreach (var material in materials)
                {
                    var materialDetail = materialDetailRepository.GetMany(x => x.MaterialFormulaID == material.ID && x.ProductModelID == order.ProductModelID).FirstOrDefault();
                    if (materialDetail != null)
                    {
                        materialCost += (materialDetail.Price ?? 0 )* (materialDetail.Quantity ?? 0);
                    }
                }

                var labours = labourFormualRepository.GetMany(x => x.DesignDetailID == item.ID);
                double labourCost = 0;
                foreach(var labour in labours)
                {
                    var labourDetail = labourDetailRepository.GetMany(x => x.LabourFormulaID == labour.ID && x.ProductModelID == order.ProductModelID).FirstOrDefault();
                    if (labourDetail != null)
                    {
                        labourCost += (labourDetail.Norm ?? 0) * (labourDetail.Quantity ?? 0);
                    }
                }

                var others = othercostFormulaRepository.GetMany(x => x.DesignDetailID == item.ID);
                double otherCost = 0;
                foreach (var other in others)
                {
                    var otherDetail = otherDetailRepository.GetMany(x => x.OtherCostFormulaID == other.ID && x.ProductModelID == order.ProductModelID).FirstOrDefault();
                    if (otherDetail != null)
                    {
                        otherCost += (otherDetail.Norm ?? 0 )*( otherDetail.Quantity ?? 0);
                    }
                }

                var tools = toolFormulaRepository.GetMany(x => x.DesignDetailID == item.ID);
                double toolCost = 0;
                foreach (var tool in tools)
                {
                    var toolDetail = toolDetailRepository.GetMany(x => x.ToolFormulaID == tool.ID && x.ProductModelID == order.ProductModelID).FirstOrDefault();
                    if (toolDetail != null)
                    {
                        toolCost += (toolDetail.Norm ?? 0) * (toolDetail.Quantity ?? 0);
                    }
                }

                var costdetai = new CostDetail()
                {
                    DesignDetail = item,
                    LabourCost=labourCost,
                    MaterialCost=materialCost,
                    ToolCost=toolCost,
                    OtherCost=otherCost,
                    TotalCost = labourCost+materialCost+otherCost+toolCost,
                };
                costDetailsFormModels.Add(costdetai);
            }
            ViewData["DesignDetail"] = designRepository.GetAll();
            ViewData["Unit"] = unitRepository.GetAll();
            ViewData["Employee"] = employeeRepository.GetAll();
            ViewData["Workplace"] = workplaceRepository.GetAll();

            var model = new OrderProcessFormModels();
            model.SubprocessDetailsFormModels = subProcess;
            model.CostDetailsFormModels = costDetailsFormModels;
            return PartialView("_OrderProcessDetail", model);
        }

        public ActionResult Save(OrderProcessFormModels frm)
        {
            var form = new OrderProcessFormModels()
            {
                ID = frm.ID,
                Code = frm.Code,
                OrderID = frm.HOrderID,
                ProductModelID = frm.ProductModelID,
                Quantity = frm.Quantity,
                Note = frm.Note,
                StartDate = frm.StartDate,
                EndDate = frm.EndDate,
            };
            var command = Mapper.Map<OrderProcessFormModels, CreateOrUpdateOrderProcessCommand>(form);
            IEnumerable<ValidationResult> errors = commandBus.Validate(command);
            ModelState.AddModelErrors(errors);
            var result = commandBus.Submit(command);

            //Them cap nhat bang subpro
            if (frm.SubprocessDetailID != null)
            {
                var lst = new List<CreateOrUpdateSubprocessDetailCommand>();
                for (int i = 0; i < frm.SubprocessDetailID.Length; i++)
                {
                    var frmDetail = new SubprocessDetailFormModels()
                    {
                        ID = frm.SubprocessDetailID[i],
                        EndDate = frm.SubprocessEndDate[i],
                        Evaluation1 = frm.SubprocessEvaluation1[i],
                        Evaluation2=frm.SubprocessEvaluation2[i],
                        ExaminerID=frm.SubprocessExaminerID[i],
                        OrderProcessID=result.ID,
                        Quantity=frm.SubprocessQuantity[i],
                        ResponsibleID=frm.SubprocessResponsibleID[i],
                        StartDate=frm.SubprocessStartDate[i],
                        State=frm.SubprocessState[i],
                        UnitID=frm.SubprocessUnitID[i],
                        WorkplaceID=frm.SubprocessWorkplaceID[i],
                        DesignDetailID=frm.SubprocessDesignDetailID[i]
                    };
                    var cmdMater = Mapper.Map<SubprocessDetailFormModels, CreateOrUpdateSubprocessDetailCommand>(frmDetail);
                    lst.Add(cmdMater);
                }
                commandBus.SubmitRange(lst);
            }
            //Them cap nhat vao bang costdetail
            if (frm.CostDetailID != null)
            {
                var lst = new List<CreateOrUpdateCostDetailCommand>();
                for (int i = 0; i < frm.CostDetailID.Length; i++)
                {
                    var frmDetail = new CostDetailFormModels()
                    {
                        ID=frm.CostDetailID[i],
                        LabourCost = frm.CostDetailLabourCost[i],
                        MaterialCost = frm.CostDetailMaterialCost[i],
                        OtherCost = frm.CostDetailOtherCost[i],
                        ToolCost = frm.CostDetailToolCost[i],
                        TotalCost = frm.CostDetailTotalCost[i],
                        DesignDetailID = frm.CostDetailDesignDetailID[i],
                        OrderProcessID=result.ID
                    };
                    var cmdMater = Mapper.Map<CostDetailFormModels, CreateOrUpdateCostDetailCommand>(frmDetail);
                    lst.Add(cmdMater);
                }
                commandBus.SubmitRange(lst);
            }

            return RedirectToAction("Index");
        }
        [HttpPost]
        public ActionResult Approve(string[] ProID)
        {
            List<CreateOrUpdateOrderCommand> listt = new List<CreateOrUpdateOrderCommand>();
            foreach (var e in ProID)
            {
                var oderprocessID = int.Parse(e);
                var oderprocesscom = oderProcessRepository.GetById(oderprocessID);
                var ordercom = oderRepository.GetById(oderprocesscom.OrderID??0);
                var command = Mapper.Map<Order, OrderFormModels>(ordercom);
                var oder = Mapper.Map<OrderFormModels, CreateOrUpdateOrderCommand>(command);
                oder.Status = 2;
                listt.Add(oder);
            }
            //Cap nhat
            commandBus.SubmitRange(listt);
            var model = oderProcessRepository.GetMany(x => x.Order.Status==1);
            return PartialView("_OrderProcessList", model.ToPagedList(1, 10));
        }
        [HttpPost]
        public ActionResult RemoveItems(string[] ProID)
        {
            ////Chuyen ve trang thai chua thuc hien san xuat
            //List<CreateOrUpdateOrderCommand> lstOrder = new List<CreateOrUpdateOrderCommand>();
            //foreach (var e in ProID)
            //{
            //    var orderID = int.Parse(e);
            //    var comand = oderProcessRepository.GetById(orderID);
            //    var oder = comand.Order;
            //    oder.Status = 0;
            //    var oderForm = Mapper.Map<Order, OrderFormModels>(oder);
            //    var oderMand = Mapper.Map<OrderFormModels, CreateOrUpdateOrderCommand>(oderForm);
            //    lstOrder.Add(oderMand);
            //}
            //commandBus.SubmitRange(lstOrder);

            //Xoa bang costerDetail
            foreach (var e in ProID)
            {
                var orderID = int.Parse(e);
                var cost = costDetailRepository.GetMany(x => x.OrderProcessID == orderID);
                if (cost.Count() > 0)
                {
                    List<DeleteCostDetailCommand> list = new List<DeleteCostDetailCommand>();
                    foreach (var item in cost)
                    {
                        var cmd = new DeleteCostDetailCommand { ID = item.ID };
                        list.Add(cmd);
                    }
                    commandBus.SubmitRange(list);
                }
            }

            //Xoa bang Subprocess
            foreach (var e in ProID)
            {
                var orderID = int.Parse(e);
                var cost = subprocessRepository.GetMany(x => x.OrderProcessID == orderID);
                if (cost.Count() > 0)
                {
                    List<DeleteSubprocessDetailCommand> list = new List<DeleteSubprocessDetailCommand>();
                    foreach (var item in cost)
                    {
                        var cmd = new DeleteSubprocessDetailCommand { ID = item.ID };
                        list.Add(cmd);
                    }
                    commandBus.SubmitRange(list);
                }
            }
            //Cap nhat
            List<DeleteOrderProcessCommand> lst = new List<DeleteOrderProcessCommand>();
            foreach (var e in ProID)
            {
                var orderID = int.Parse(e);
                var command = new DeleteOrderProcessCommand { ID = orderID };
                lst.Add(command);
            }
            commandBus.SubmitRange(lst);
            var model = oderProcessRepository.GetMany(x => x.Order.Status == 1);
            return PartialView("_OrderProcessList", model.ToPagedList(1, 10));
        }
        [HttpGet]
        [ValidateInput(false)]
        public ActionResult Page(int PageID)
        {
            var oder = oderProcessRepository.GetAll().OrderBy(x => x.Code);
            return PartialView("_OrderProcessList", oder.ToPagedList(1, PageID));
        }
        [HttpGet]
        public ActionResult Search(string Name)
        {
            IEnumerable<OrderProcess> model;
            if (String.IsNullOrEmpty(Name))
            {
                model = oderProcessRepository.GetAll();
            }
            else
            {
                model = oderProcessRepository.GetMany(x => (x.Code.Contains(Name)) || (x.Order.Code.Contains(Name)));

            }
            return PartialView("_OrderProcessList", model.ToPagedList(1, 10));
        }

    }
}
